package com.powernode.ssm;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.pool.DruidDataSource;

import javax.sql.DataSource;
import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class SqlRunnerMain {

    // ==================== 默认数据库配置（可被参数覆盖）====================
    // 可通过命令行第一个参数指定数据库类型，如：mysql、postgresql、oracle
    private static String dbType = "mysql"; // 默认是 mysql

    // 各数据库的配置类：驱动类、URL 模板、默认用户名、默认密码
    // Java 8 不支持 Map.of，改用 HashMap
    private static final Map<String, DbConfig> DB_CONFIGS;

    static {
        Map<String, DbConfig> map = new HashMap<>();
        map.put("mysql", new DbConfig(
                "com.mysql.cj.jdbc.Driver",
                "jdbc:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8",
                "root",
                "123"
        ));
        map.put("postgresql", new DbConfig(
                "org.postgresql.Driver",
                "jdbc:postgresql://localhost:5432/your_database",
                "postgres",
                "postgres"
        ));
        map.put("oracle", new DbConfig(
                "oracle.jdbc.OracleDriver",
                "jdbc:oracle:thin:@localhost:1521:ORCLCDB",
                "system",
                "oracle"
        ));
        // 如需支持 SQL Server，可继续添加
        DB_CONFIGS = Collections.unmodifiableMap(map);
    }

    private static final String SQL_DIR = "sql"; // classpath:/sql/

    public static void main(String[] args) {
        System.out.println("🚀 开始执行 SQL 初始化...");

        // 1. 从命令行参数获取数据库类型，默认为 mysql
        if (args.length > 0) {
            dbType = args[0].toLowerCase().trim();
        }

        DbConfig config = DB_CONFIGS.get(dbType);
        if (config == null) {
            System.err.println("❌ 不支持的数据库类型: " + dbType);
            System.err.println("✅ 支持的数据库类型有: " + DB_CONFIGS.keySet());
            return;
        }

        System.out.println("🔌 当前选择的数据库类型: " + dbType);
        System.out.println("📌 使用配置: Driver=" + config.driver + ", URL=" + config.url + ", User=" + config.username);

        // 2. 初始化 Druid 数据源
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(config.driver);
        dataSource.setUrl(config.url);
        dataSource.setUsername(config.username);
        dataSource.setPassword(config.password);
        dataSource.setInitialSize(1);
        dataSource.setMaxActive(10);

        // 3. 自动扫描 classpath:/sql/ 下所有 .sql 文件
        List<ClassPathResource> sqlResources;
        try {
            sqlResources = scanSqlFilesFromClasspath();
        } catch (Exception e) {
            System.err.println("❌ 扫描 SQL 文件失败: " + e.getMessage());
            e.printStackTrace();
            return;
        }

        if (sqlResources.isEmpty()) {
            System.out.println("ℹ️ 未找到任何 SQL 文件，请确认 classpath:/sql/ 下有 .sql 文件（如 target/classes/sql/）");
            return;
        }

        System.out.println("✅ 找到 " + sqlResources.size() + " 个 SQL 文件，开始执行...");

        // 4. 逐一执行 SQL 文件
        for (ClassPathResource resource : sqlResources) {
            System.out.println("📄 正在执行 SQL 文件: " + resource.getName());
            executeSqlFile(resource, dataSource);
        }

        System.out.println("🎉 所有 SQL 文件执行完成！");
    }

    /**
     * 数据库配置类（Java 8 不支持 record，改用普通类）
     */
    private static class DbConfig {
        final String driver;
        final String url;
        final String username;
        final String password;

        DbConfig(String driver, String url, String username, String password) {
            this.driver = driver;
            this.url = url;
            this.username = username;
            this.password = password;
        }

        @Override
        public String toString() {
            return "Driver: " + driver + ", URL: " + url + ", User: " + username;
        }
    }

    /**
     * ✅ 自动扫描 classpath:/sql/ 下所有 .sql 文件（支持 IDE 和 JAR 包）
     */
    private static List<ClassPathResource> scanSqlFilesFromClasspath() throws Exception {
        List<ClassPathResource> resources = new ArrayList<>();
        String sqlDirPath = "sql/";

        URL sqlDirUrl = SqlRunnerMain.class.getClassLoader().getResource(sqlDirPath);
        if (sqlDirUrl == null) {
            System.out.println("⚠️ 未找到 classpath:/sql/ 目录");
            return resources;
        }

        String protocol = sqlDirUrl.getProtocol();

        if ("file".equals(protocol)) {
            // 文件系统模式（如 IDE）
            String decodedPath = URLDecoder.decode(sqlDirUrl.getFile(), StandardCharsets.UTF_8.name());
            File sqlDir = new File(decodedPath);
            if (sqlDir.exists() && sqlDir.isDirectory()) {
                File[] sqlFiles = sqlDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".sql"));
                if (sqlFiles != null) {
                    for (File file : sqlFiles) {
                        String resourcePath = "sql/" + file.getName();
                        resources.add(new ClassPathResource(resourcePath));
                    }
                }
            }
        } else if ("jar".equals(protocol)) {
            // JAR 包模式
            JarURLConnection jarConn = (JarURLConnection) sqlDirUrl.openConnection();
            JarFile jarFile = jarConn.getJarFile();
            Enumeration<JarEntry> entries = jarFile.entries();

            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                String entryName = entry.getName();

                if (entryName.startsWith(sqlDirPath) && entryName.toLowerCase().endsWith(".sql") && !entry.isDirectory()) {
                    String sqlFileName = entryName.substring(sqlDirPath.length());
                    String resourcePath = "sql/" + sqlFileName;
                    resources.add(new ClassPathResource(resourcePath));
                }
            }
            jarFile.close();
        }

        return resources;
    }

    /**
     * 执行单个 SQL 文件内容
     */
    private static void executeSqlFile(ClassPathResource resource, DataSource dataSource) {
        try (
                InputStream is = resource.getStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
                Connection conn = dataSource.getConnection();
                Statement stmt = conn.createStatement()
        ) {
            StringBuilder sqlBuilder = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                line = StrUtil.trim(line);
                if (StrUtil.isBlank(line) || line.startsWith("--") || line.startsWith("#")) {
                    continue;
                }

                sqlBuilder.append(line);

                if (line.endsWith(";")) {
                    String sql = sqlBuilder.toString().replace(";", "").trim();
                    if (StrUtil.isNotBlank(sql)) {
                        System.out.println("[SQL] 执行: " + StrUtil.sub(sql, 0, 80) + "...");
                        stmt.execute(sql);
                    }
                    sqlBuilder = new StringBuilder();
                } else {
                    sqlBuilder.append("\n");
                }
            }

            // 处理最后一行没有分号的情况
            String remaining = sqlBuilder.toString().trim();
            if (StrUtil.isNotBlank(remaining)) {
                System.out.println("[SQL] 执行剩余: " + StrUtil.sub(remaining, 0, 80) + "...");
                stmt.execute(remaining);
            }

            System.out.println("✅ 执行成功: " + resource.getName());

        } catch (Exception e) {
            System.err.println("❌ 执行失败 [" + resource.getName() + "]: " + e.getMessage());
            e.printStackTrace();
        }
    }
}